package main.UI;

import main.UI.misc.ErrorHandling;
import main.database.DatabaseException;
import main.database.SQLDatabaseManager;
import main.database.entity.Category;
import main.database.entity.MyEntity;
import main.database.entity.Product;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

public class CategoryPropertiesDialog extends JDialog{
    private JPanel contentPane;
    private JButton buttonOK;
    private JButton buttonCancel;
    private JTable table;
    private JTextField categoryField;
    private JButton deleteButton;
    private JButton addButton;
    private String formerName;
    private List<ProductNameAndId> productsToAdd = new ArrayList<ProductNameAndId>();
    private List<ProductNameAndId> productsToRemove = new ArrayList<ProductNameAndId>();
    private List<ProductNameAndId> categoryProducts = new ArrayList<ProductNameAndId>();
    private Long changedCategoryID;
    private SQLDatabaseManager mngr = GUI.getSQLManager();

    private static final Color ERROR_BACKGROUND_COLOR = new Color( 255, 215, 215 );

    //TODO don't save every product in category, save with category with added elements! Set in properties of category cascade = save-update on product list option
    public CategoryPropertiesDialog(Long id, String catName) throws DatabaseException{
        formerName = catName;
        changedCategoryID = id;
        setContentPane(contentPane);
        setModal(true);
        getRootPane().setDefaultButton(buttonOK);
        setTitle("Изменить категорию");
        categoryField.setText(catName);

        final DefaultTableModel tableModel = new DefaultTableModel() {

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        table.setModel(tableModel);
        table.setRowHeight(20);

        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        tableModel.addColumn("Наименование");
        table.setTableHeader(null);

            List productList = mngr.getFilteredProductsFromDB(catName);
            String n;
        for (Object aProduct : productList) {
            Product product = (Product) aProduct;
            n = product.getName();
            categoryProducts.add(new ProductNameAndId(product.getId(), n));
            tableModel.addRow(new Object[]{n});
        }



        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    SelectEntryDialog selectDialog = new SelectEntryDialog(true, false);
                    selectDialog.pack();
                    GUI.centerDialog(selectDialog);
                    selectDialog.setVisible(true);
                    setProductField(selectDialog.getItem());
                }
                catch (DatabaseException ex) {
                    ErrorHandling.showError(ex, "Ошибка при обращении к базе данных", false);
                }
            }
        });


        /*createButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                *//*ProductDialog productDialog = new ProductDialog(thisDialog, (long) 0, "", formerName);
                productDialog.pack();
                GUI.centerDialog(productDialog);
                productDialog.setVisible(true);*//*

                String productName = productField.getText();
                if (productName.trim().equals(""))
                {
                    productField.setBackground(ERROR_BACKGROUND_COLOR);
                    GUI.showError(null, "Имя продукта не может быть пустым", false);
                    return;
                }
                if ((!productsToCommit.contains(productName)) && (mngr.getIDByName(MyEntity.PRODUCT, productName) == 0))
                {
                    productsToCommit.add(productName);
                    addNewTableEntry(productName);
                }
                else {
                    productField.setBackground(ERROR_BACKGROUND_COLOR);
                    GUI.showError(null, "Продукт с таким именем уже существует", false);
                }
            }
        });
*/
        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selectedRow = table.getSelectedRow();
                if (selectedRow == -1)
                    return;
                String productToDelete = (String) table.getValueAt(selectedRow,0);
                removeSelectedTableEntry(tableModel);
                    //if (!productsToCommit.remove(productToDelete)) {
                        for (ProductNameAndId note : productsToAdd)
                        {
                            if (note.getName().equals(productToDelete))
                            {
                                productsToAdd.remove(note);
                                return;
                            }
                        }
                        Long id = (long) 0;
                        for(ProductNameAndId note : categoryProducts) {
                            if (note.getName().equals(productToDelete)) {
                                id = note.getId();
                                break;
                            }
                        }
                            if (id == 0) {
                                ErrorHandling.showError(null, "Такого продукта не существует в данной категории", false);
                                System.out.println("Эта ошибка не должна появляться");
                                return;
                            }
                            productsToRemove.add(new ProductNameAndId(id, productToDelete/*, ProductNameAndId.REMOVE*/));
                    //}
            }
        });

        buttonOK.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onOK();

            }
        });

        buttonCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        });

        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                onCancel();
            }
        });

    }

    private void onOK() {
        String newName = categoryField.getText();
        if (newName.trim().equals("")) {
            categoryField.setBackground(ERROR_BACKGROUND_COLOR);
            ErrorHandling.showError(null, "Имя категории не может быть пустым", false);
            return;
        }

        try {
            if (newName.equals(formerName))
            {
                //Do nothing
            }
            else if (mngr.getIDByName(MyEntity.CATEGORY, newName) == 0)
            {
                mngr.saveCategory(newName, changedCategoryID);
                GUI.changeCategoryEntry(newName);
            }
            else {
                categoryField.setBackground(ERROR_BACKGROUND_COLOR);
                ErrorHandling.showError(null, "Категория с таким именем уже существует", false);
                return;
            }

        for(ProductNameAndId product : productsToRemove) {
                mngr.saveProduct(product.getName(), Category.NO_CATEGORY_WITH_TAGS, product.getId());
        }
        for(ProductNameAndId product : productsToAdd)
                mngr.saveProduct(product.getName(), newName, product.getId());
        }
        catch (DatabaseException ex) {
            ErrorHandling.showError(ex, "Ошибка при обращении к базе данных", false);
            dispose();
            return;
        }
        //If products have changed - update tables
        if ((productsToRemove.size()!=0) || (productsToAdd.size()!=0)) {
            /*Reason GUI.changeProductEntry is not used,
                to change table entry, method must have a number of changed row,
                but as we are not changing from main product table we don't know row of
                changed product.
            */
            try {
                GUI.updateProductTable();
                GUI.updateExpenseTable();
            }
            catch (DatabaseException ex) {
                ErrorHandling.showError(ex, "Ошибка при обновлении записей", false);
            }
        }
        dispose();
    }

    private void onCancel() {
// add your code here if necessary
        dispose();
    }

    public void addNewTableEntry(String name) {
        ((DefaultTableModel) table.getModel()).addRow(new Object[]{name});
    }

    private void removeSelectedTableEntry(DefaultTableModel tableModel) {
        tableModel.removeRow(table.getSelectedRow());
    }

    /*private void updateColor(Component cmp) {
        cmp.setBackground(null);
    }*/


    //TODO MVC
    public void setProductField(String product) {
        //Check if product was scheduled for removal
        for (ProductNameAndId note : productsToRemove)
        {
            if (note.getName().equals(product))
            {
                productsToRemove.remove(note);
                addNewTableEntry(product);
                return;
            }
        }
        //If product is already in category
        for (int rowCnt = 0; rowCnt < table.getRowCount(); rowCnt++)
        {
            if (table.getValueAt(rowCnt, 0).equals(product))
                return;
        }
        //else
        try {
        productsToAdd.add(new ProductNameAndId(mngr.getIDByName(MyEntity.PRODUCT, product),
                product));
        }
        catch (DatabaseException ex) {
            ErrorHandling.showError(ex, "Ошибка при обращении к базе данных", false);
            return;
        }
        addNewTableEntry(product);
    }


    //A quick note about product containing name and id.
    //Used in separate list to bind name and id of products together
    class ProductNameAndId {
        private Long id;
        private String name;


        public ProductNameAndId(Long id, String name/*, int action*/) {
            this.id = id;
            this.name = name;
        }

        String getName() {
            return name;
        }

        Long getId() {
            return id;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null)
                return false;
            if (getClass() != o.getClass())
                return false;
            ProductNameAndId other = (ProductNameAndId) o;
            if (!id.equals(other.id))
                return false;
            if (!name.equals(other.name))
                return false;
            return true;
        }

        @Override
        public int hashCode() {
            return 1;
        }
    }

}
